/**
 * \file tsm.c
 * \brief 
 * \author Somayya ELMATA
 * \author Theo BRASSEUR
 * \version 0.1
 * \date 25/12/2013
 *
 * Ce fichier qui contient les fonctions pour la lecture de fichier calcul 
 * des chemins etc... 
 *
 */

#ifndef TSM
#define TSM 
#include "tsm.h"
#endif

/**
 * \fn Ville* get_city(char *file_name)
 * \brief lire le fichier d'informations .vl 
 *
 * \param nom de fichier
 * \return liste des villes
 */
City* get_city(char* file_name)
{
	City* city = NULL;
	int i = 0, nbrcity = 0;
	FILE *file = fopen(file_name,"r");

	if( test_file(file) == 0 )
	{		
		nbrcity = get_nbr_city(file); // necessaire avant la declaration d'Info_cityS
		city = malloc(sizeof(City) * nbrcity);
		
		for(i = 0; i < nbrcity; i++)
		{
			city[i].name = malloc( sizeof(char) * strlen(get_city_name(file, i)) ); // +1 a verifier /* FIXME */
			
			strcpy(city[i].name, get_city_name(file, i)); 
			city[i].x = get_coord_x(file, i);
			city[i].y = get_coord_y(file, i);
		}	
	}
	
	if(city == NULL)
		printf("Erreur get_city\nFichier ville invalide\n");
	
	fclose(file);
	
	return city;
}

/**
 * \fn int get_nbr_city(FILE file)
 * \brief lit le nombre de villes dans le fichier
 *
 * \param le fichier 
 * \return le nombre de ville dans le fichier
 */
int get_nbr_city(FILE *file)
{
	int nbrcity = -1;

    file = lire_apres(file, "#Nombre_de_villes");
	fscanf(file, "%d", &nbrcity);
	
	if(nbrcity == -1) 
		printf("Echec get_nbr_city\nVérifier que le fichier .vl est valide\n");
	
	return nbrcity;
}

/**
 * \fn int test_struct_file(char *file_name)
 * \brief test si le fichier à une format correcte
 *
 * \param le fichier à verifier
 * \return 0 si le fichier est correcte autre chose sinon
 */
int test_struct_file(FILE *file)
{	
	char str[MAX_CHAR];
	
	fscanf(file,"%s",str);
	if(strcmp(str, "#Nombre_de_villes")==0)
	{
		next_line(file);next_line(file);
		fscanf(file,"%s",str);
		if(strcmp(str, "#Position_des_villes")==0)
			return 0;
	}
	return -1;
}

/**
 * \fn int test_nbr_city(FILE* file)
 * \brief test sur le nombre des villes est le meme qui est declarer dans le fichier
 *
 * \param le fichier à verifier
 * \return 0 si le fichier est correcte autre chose sinon
 */
int test_nbr_city(FILE* file)
{
	int realnbr = 0;
	char line[10];
	
    file = lire_apres(file, "#Position_des_villes");
    
    while(fgets ( line, sizeof(line), file) != NULL)
		if(line[0] >= 'A' && line[0] <= 'Z')
			realnbr++;
	
	if(get_nbr_city(file) != realnbr) 
	{
		printf("Echec test_nbr_city\nVérifier que le fichier .vl est valide\n"); 
		return -1;
	}
		
	return 0;
}

/**
 * \fn int test_file(char *file_name)
 * \brief test si le fichier est correcte
 *
 * \param le fichier à verifier
 * \return 0 si le fichier est correcte autre chose sinon
 */
int test_file(FILE *file)
{
	int err = 0;
	
	if( (err=test_nbr_city(file)) ){
		
		 err=test_struct_file(file);
	}
		
	return err;
}

/**
 * \fn void print_info_city(City* city)
 * \brief affichage des informations et distances (tab 2D) 
 *
 * \param liste des villes
 */
void print_info_city(City city)
{
	printf("nom de ville : %s\n",city.name);
	printf("\tx = %ld \t y = %ld\n\n",city.x,city.y);
}

/**
 * \fn FILE* lire_apres(FILE* file, char* chaine)
 * \brief place la tete de lecture apres la chaine de caractere passée en parametre
 *
 * \param le fichier sur lequel on deplace la tete de lecture, la chaine de caractere recherchée
 * \return le fichier avec la tete de lecture déplacée ou ne déplace pas la tete de lecture si la chaine n'est pas trouve.
 */
FILE* lire_apres(FILE* file, char* chaine)
{	
	int i = 0;
	char* line = malloc(sizeof(char) * strlen(chaine) );
	FILE* save = file;

	rewind(file);
	
	while(strcmp(line, chaine) != 0 && ++i < 50)
		fgets ( line, (int) (strlen(chaine) + 1), file );  
		  
    
    if( i == 50)
    {
		printf("Echec lire_apres\nLa chaine de caractere n'a pas ete trouve dans le fichier\n");
		file = save;	
	}
	return file;
}

/**
 * \fn int test_filename(char* file_name)
 * \brief test la validite du fichier ville passe en parametre au programme
 *
 * \param le nom du fichier ville passer en parametre au programme
 * \return 0 si OK. -1 sinon
 */
int test_filename(char* file_name)
{
	FILE* file = fopen(file_name, "r");
	
	if (file == NULL)
	{
		printf("Le fichier ville: %s specifie en parametre n'existe pas.\n", file_name);
		return -1;
	}
	
	else if( ( strlen(file_name) < 4 ) | ( str_istr(file_name, ".vl") != strlen(file_name) - 3 ) )
	{
		printf("Extension incorrect.\nLe fichier doit porter l'extension .vl\n");
		close(file);
		return -1;
	} 
	close(file);
	return 0;
}

/**
 * \fn str_istr (const char *cs, const char *ct)
 * \brief indique l'index de la premiere occurence d'une sous chaine de caractere dans une autre
 *
 * \param 
 * \return l'index de la sous chaine recherche
 */
int str_istr (const char *cs, const char *ct)
{
   int index = -1;

   if (cs != NULL && ct != NULL)
   {
      char *ptr_pos = NULL;

      ptr_pos = strstr (cs, ct);
      if (ptr_pos != NULL)
      {
         index = ptr_pos - cs;
      }
   }
   return index;
}	

/**
 * \fn char* get_city_name(FILE* file, int indice)
 * \brief retourne le nom de la ville n°(i+1) du fichier
 *
 * \param le fichier ville, le numéro de la ville voulue
 * \return nom de la ville
 */
char* get_city_name(FILE* file, int indice)
{
	char city_name[MAX_CHAR];
	char *s;
	int i = 0;
	
	file = lire_apres(file, "#Position_des_villes");
	
	for(i = 0; i < indice+1; i++)
		next_line(file);	
	
	fscanf(file,"%s",city_name);
	s = malloc(sizeof(char)*strlen(city_name));	
	strcpy(s,city_name);
	return s;
}

/**
 * \fn get_coord_x(FILE* file, int indice)
 * \brief recupere la coord x, y de la ville a l indice voulu
 *
 * \param le fichier, l indice
 * \return coordonnée x, y
 */
int get_coord_x(FILE* file, int indice)
{
	int x = -1,  i = 0;
	
	file = lire_apres(file, "#Position_des_villes");
	
	for(i = 0; i < indice+1; i++)
		next_line(file);	
	
	while(fgetc(file) != ' ');
	
	fscanf(file, "%d", &x);
	
	return x;
}

/**
 * \fn get_coord_y(FILE* file, int indice)
 * \brief recupere la coord  y de la ville a l indice voulu
 *
 * \param le fichier, l indice
 * \return coordonnée  y
 */
int get_coord_y(FILE* file, int indice)
{
	int y = -1,  i = 0;
	
	file = lire_apres(file, "#Position_des_villes");
	
	for(i = 0; i < indice+1; i++)
		next_line(file);	
	
	while(fgetc(file) != ' ');
	while(fgetc(file) != ' ');
	
	fscanf(file, "%d", &y);
	return y;
}

/**
 * \fn void print_all_city(City* c)
 * \brief afficher la liste des villes
 *
 * \param la liste des villes
 */
void print_all_city(City* c, int nbrcity)
{
	int i;
	
	if(c == NULL)
		printf("aucune ville n'a ete chargée\n");
	
	for(i = 0;i < nbrcity; i++)
	{
		printf("%d) ",i);
		print_info_city(c[i]);
	}	
}

/**
 * \fn double compute_dst(City city1,City city2)
 * \brief calcule la distance entre deux villes
 *
 * \param la premiere ville 
 * \param la 2eme ville
 * \return la distance entre deux villes 
 */
double compute_dst(City city1,City city2)
{
	double dist = 0;
		dist = sqrt( pow((city2.x - city1.x), 2) + pow( (city2.y - city1.y), 2) );
	return dist;
}

/**
 * \fn void compute_all_dst(City *c,double** mat, int nbrcity)
 * \brief calcul la matrice des distances entre les villes
 *
 * \param la liste des villes
 * \param la matrice des distances
 */
double** compute_all_dst(City *c, int nbrcity)
{
	int i,j;
	double** mat = NULL;
	double* mat_aux = NULL;
	
	mat = malloc(sizeof(double*) * nbrcity);
	mat_aux = malloc(sizeof(double) * nbrcity * nbrcity);
	
	for(i = 0; i < nbrcity; i++)
		mat[i] = &mat_aux[i * nbrcity];
	
	for(i=0;i<nbrcity;i++)
		for(j=0;j<nbrcity;j++)	
			mat[i][j]=compute_dst(c[i],c[j]);	
			
	return mat;
}
/**
 * \fn void print_matrix(City *c, double** mat, int nbrcity) 
 * \brief afficher les distances entre les villes
 *
 * \param la liste des villes
 * \param la matrice des distances
 */
void print_matrix(City *c, double** mat, int nbrcity) 
{
	int i,j;
	
	printf("\n\n\t");
	
	for(i = 0; i < nbrcity;i++)
	{
		printf("\t\t %s",c[i].name);
	}

	for(i = 0; i < nbrcity; i++)
	{
		printf("\n\t %s\t",c[i].name);
		
		for(j = 0; j < nbrcity; j++)
		{	
			printf("\t%lf",mat[i][j]);
		}
	}
		
	printf("\n\n");	
}

/**
 * \fn void next_line(FILE* file)
 * \brief passer à la ligne suivante
 *
 * \param le fichier
 * \return 0 si tout se passe bien -1 si la fin de fichier
 */
int next_line(FILE* file)
{
        char c;
       
        while((c=fgetc(file)) != EOF)
                if (c == '\n') {return 0;}
        return -1;
}
/**
 * \fn double compute_path(Path chemin)
 * \brief calcule la longueur d'un trajet
 *
 * \param le trajet a calculer
 * \return la longueur de ce trajet
 */
double compute_path(Path chemin)
{
	int i = 0;
	double distance = 0;
	
	for(i = 0; i < chemin.longueur -1; i++)
		distance += compute_dst(chemin.city[i], chemin.city[i+1]);
	distance += compute_dst(chemin.city[chemin.longueur-1], chemin.city[0]);
	
	return distance;
}

void print_path(Path chemin)
{
	int i = 0;
	FILE *file;
	file = fopen ("resultat","a");
	if(chemin.city == NULL)
		printf("\nchemin NULL\n");
	for(i = 0; i < chemin.longueur; i++)
	{
		printf("%s  ",  chemin.city[i].name);
		fprintf(file,"%s  ",  chemin.city[i].name);
		
	}
	
	printf("\t ::: longeur : %lf", chemin.dst_path);
	fprintf(file,"\t ::: longeur : %lf", chemin.dst_path);
	printf("\n");
	fprintf(file,"\n");
	fclose(file);
}

int nombre(City* city)
{
	int i = 0;
	int nbr = 0;
	
	for(i = 0 ; city->name != NULL; i++) 
		nbr ++;
	
	return nbr;
}

int load_file(City** city, int* nbrcity)
{
	FILE* file = NULL;
	char* filename= NULL;
	do
	{
			filename = saisie_filename();
			
	}while( test_filename(filename) != 0 );
	
	file = fopen(filename, "r");
	
	if( ! test_file(file) )
	{
		*city = get_city(filename);
		*nbrcity = get_nbr_city(file);	
	}
	return 0;
}


